######################################################################################
#
# This file was provided as part of the SharePoint Mystery Deployment package
# Created by Christopher Kimbell (http://sharepointmystery.com)
#
######################################################################################

# -----------------------------------------------------------------
# Creates an object used to manipulate the farm
# -----------------------------------------------------------------
function New-Farm()
{
    $obj=new-object PSObject -Property @{
        # semicolon separated list of solutions
        Solutions = @();
        # name of account running the timer service
        TimerAccount = "";
        TimerAccountCredentials = $null;
        # account used for deployment
        DeploymentAccount = "";
        # semicolon separated list of servers
        Servers = @();
        # indicates if databases should be created
        CreateDatabases= $false;
        # indicates if database folders should be created, mostly applicable on dev machines
        CreateDatabaseFolders = $false;
        # indicates if SPN's should be registered
        RegisterSPN = $false;
        # The start path for all IIS paths
        IisRoot = "";
        # name of database server
        DatabaseServer = "";
        # prefix added to various values to identify the owning farm
        Prefix = "";
        # value to append to default URL and host header
        DefaultUrlDomain = "";
		CustomUrlDomain = "";
		ExtranetUrlDomain = "";
		InternetUrlDomain = "";
		IntranetUrlDomain = "";
		Diagnostics = New-Diagnostics;
    }
    # -----------------------------------------------------------------
    # Validates the information in the object
    # -----------------------------------------------------------------
    Add-Method $obj "Validate" `
    {   
        Write-Operation "Validating Farm"  
        #Validate-NotEmpty "Servers" $this.Servers
        Validate-NotEmpty "TimerAccount" $this.TimerAccount
        Validate-NotEmpty "IisRoot" $this.IisRoot
        Validate-NotEmpty "DatabaseServer" $this.DatabaseServer
        Validate-NotEmpty "Prefix" $this.Prefix
        Validate-NotEmpty "DefaultUrlDomain" $this.DefaultUrlDomain
		
		$this.Diagnostics.Validate()
    }
	# -----------------------------------------------------------------
    # Configures the farm
    # -----------------------------------------------------------------
    Add-Method $obj "PrepareServers" `
    {
        $this.Diagnostics.PrepareServers()
    }
    # -----------------------------------------------------------------
    # Provisions the farm
    # -----------------------------------------------------------------
    Add-Method $obj "Provision" `
    {
        Write-Operation "TODO: Provisioning Farm"
    }
	# -----------------------------------------------------------------
    # Configures the farm
    # -----------------------------------------------------------------
    Add-Method $obj "Configure" `
    {
		$this.Diagnostics.PrepareServers()
        $this.Diagnostics.Configure()
    }
     # -----------------------------------------------------------------
    # Deploys the globally scoped solutions
    # -----------------------------------------------------------------
    Add-Method $obj "DeploySolutions" `
    {
		foreach ($name in $this.Solutions) 
        {
            $solution = Add-Solution $name
            if($solution.ContainsWebApplicationResource -eq $false)
            {
                if($solution.Deployed -eq $true)
                {
                    Write-OperationDone "Solution $($name) has already been deployed"
                }
                else
                {
                    Write-Operation "Deploying solution $($name)"
                    Install-SPSolution -Identity $name `
                        -GACDeployment `
                        -CASPolicies
                    
                    Wait-Solution $name
                }
            }
            else
            {
                Write-Warning "Solution $($name) cannot be deployed globally since it's scoped to a web application"
            }
        }
    }
    # -----------------------------------------------------------------
    # Retracts the globally scoped solutions
    # -----------------------------------------------------------------
    Add-Method $obj "RetractSolutions" `
    {       
        foreach ($name in $this.Solutions) 
        {
            $solution = Get-SPSolution | Where-Object {$_.Name -eq $name}
            if($solution -ne $null -and $solution.Deployed -eq $true)
            {
                if($solution.ContainsWebApplicationResource -eq $false)
                {
                    Write-Operation "Retracting solution $(name)"
                    Uninstall-SPSolution -Identity $solution  -Confirm:$false
                    Wait-Solution $name 
                }
                else
                {
                    Write-Warning "Solution $($name) cannot be retracted globally since it's scoped to a web application"
                }
                
                # if it's no longer deployed, we can remove it
                if($solution.Deployed -eq $false)
                {
                    Remove-SPSolution -Identity $solution -Confirm:$false
                }
            }
        }
    }
    # -----------------------------------------------------------------
    # Resolves the credentials
    # -----------------------------------------------------------------
    Add-Method $obj "ResolveCredentials" `
    {
        if($this.TimerAccountCredentials -eq $null)
        {
			# use an approach that doesn't prompt for password; use information in managed account 
			$account = Register-ManagedAccount($this.TimerAccount)
			$password = Get-ManagedAccountPassword($account)
			$this.TimerAccountCredentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $this.TimerAccount,$password
		
            #$this.TimerAccountCredentials = Get-Credential $this.TimerAccount
        }
		return $this.TimerAccountCredentials
    }
    return $obj
}